using Xunit;

namespace Viyi.Util.Test.Linq {
    public partial class TestMaxMin {
        private readonly Model<int>[] intModels = Model.From(new int[]
        {
            1, 2, 3, 4, 5,
            int.MinValue,
            6, 7, 8, 9, 10,
            int.MaxValue,
            int.MinValue,
            11, 12, 13, 14, 15
        });

        [Fact]
        public void TestMaxMinUInt64() {
            var data = Model.From(new ulong[]
            {
                1, 2, 3, 4, 5,
                ulong.MinValue,
                ulong.MaxValue,
                6, 7, 8, 9, 10
            });

            Assert.Equal(ulong.MaxValue, data.MaxBy(m => m.Value)?.Value);
            Assert.Equal(ulong.MinValue, data.MinBy(m => m.Value)?.Value);

            Assert.Equal(ulong.MaxValue,
                Model.From(new[] {
                    ulong.MaxValue
                }).MaxBy(m => m.Value)?.Value);

            Assert.Equal(ulong.MaxValue,
                Model.From(new[] {
                    ulong.MaxValue
                }).MinBy(m => m.Value)?.Value);

            Assert.Equal(ulong.MaxValue,
                Model.From(new[] {
                    ulong.MaxValue, ulong.MinValue
                }).MaxBy(m => m.Value)?.Value);

            Assert.Equal(ulong.MinValue,
                Model.From(new[] {
                    ulong.MaxValue, ulong.MinValue
                }).MinBy(m => m.Value)?.Value);
        }

        [Fact]
        public void TestMaxMinUInt32() {
            var data = Model.From(new int[]
            {
                1, 2, 3, 4, 5,
                int.MinValue,
                int.MaxValue,
                6, 7, 8, 9, 10
            });

            Assert.Equal(int.MaxValue, data.MaxBy(m => m.Value)?.Value);
            Assert.Equal(int.MinValue, data.MinBy(m => m.Value)?.Value);

            Assert.Equal(int.MaxValue,
                Model.From(new[] {
                    int.MaxValue
                }).MaxBy(m => m.Value)?.Value);

            Assert.Equal(int.MaxValue,
                Model.From(new[] {
                    int.MaxValue
                }).MinBy(m => m.Value)?.Value);

            Assert.Equal(int.MaxValue,
                Model.From(new[] {
                    int.MaxValue, int.MinValue
                }).MaxBy(m => m.Value)?.Value);

            Assert.Equal(int.MinValue,
                Model.From(new[] {
                    int.MaxValue, int.MinValue
                }).MinBy(m => m.Value)?.Value);
        }
    }
}

namespace Viyi.Util.Test.Linq {
    // Nested classes

    public partial class TestMaxMin {
        private static class Model {
            public static Model<T>[] From<T>(IEnumerable<T> values) {
                return values
                    .Select((v, i) => new Model<T>(i, v))
                    .ToArray();
            }
        }

        private class Model<T> {
            public int Index { get; }
            public T Value { get; }

            public Model(int index, T value) {
                Index = index;
                Value = value;
            }
        }
    }
}
